package com.nb.java14.BlackBerry.ui.widgets;

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.VerticalFieldManager;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * @author Nahuel Barrios.
 * @version 1.0
 * @since 20/07/2010.
 */
public class FormField extends VerticalFieldManager {

	public static final int STYLE_READ_ONLY = 1;
	public static final int STYLE_EDITABLE = 2;
	public static final int STYLE_FIELD_CUSTOM = 3;

	private Hashtable _fields = new Hashtable();
	private int _columns;
	private int[] _columnsWidth = null;
	private int _style;
	private boolean _addSeparator = true;
	private int _maximumChars = 10;//  ToDo: Functionality: ver esto!!!

	/**
	 * Coloca la primer linea separatoria, siempre y cuando el formulario este seteado de manera tal que el resto de las
	 * filas tienen tambien esta linea separatoria
	 */
	protected void putFirstSeparator() {
		if (_addSeparator)
			this.add(new SeparatorField());
	}

	/**
	 * Crea un nuevo objeto de tipo FormField listo para agregar campos. Por default se colocara una linea separatoria
	 * entre "fila" y "fila". Ademas, por default la cantidad de columnas sera de 2, y como no se indica el ancho de las
	 * mismas entonces seran del mayor ancho posible y de igual ancho cada.
	 *
	 * @param style El estilo de la segunda columna del formulario, puede ser STYLE_READ_ONLY, STYLE_EDITABLE,
	 *              STYLE_FIELD_CUSTOM. En caso de indicar un valor distinto a uno de estos, se creara el campo como
	 *              STYLE_READ_ONLY.
	 */
	public FormField(int style) {
		super();
		_style = style;
		_columns = 2;
		this.putFirstSeparator();
	}

	/**
	 * Crea un nuevo objeto de tipo FormField listo para agregar campos. Por default se colocara una linea separatoria
	 * entre "fila" y "fila".
	 *
	 * @param style   El estilo de la segunda columna del formulario, puede ser STYLE_READ_ONLY, STYLE_EDITABLE,
	 *                STYLE_FIELD_CUSTOM. En caso de indicar un valor distinto a uno de estos, se creara el campo como
	 *                STYLE_READ_ONLY.
	 * @param columns La cantidad de columnas que tendra el formulario. Como no se indica el ancho de las mismas entonces
	 *                seran del mayor ancho posible y de igual ancho cada.
	 */
	public FormField(int style, int columns) {
		super();
		_style = style;
		_columns = columns;
		this.putFirstSeparator();
	}

	/**
	 * Crea un nuevo objeto de tipo FormField listo para agregar campos. Por default se colocara una linea separatoria
	 * entre "fila" y "fila".
	 *
	 * @param style		El estilo de la segunda columna del formulario, puede ser STYLE_READ_ONLY, STYLE_EDITABLE,
	 *                     STYLE_FIELD_CUSTOM. En caso de indicar un valor distinto a uno de estos, se creara el campo como
	 *                     STYLE_READ_ONLY.
	 * @param columnsWidth Un array de ints conteniendo la medida de cada columna. La sumatoria de los elementos debe ser
	 *                     igual al maximo ancho disponible de pantalla. Para el BlackBerry 8310 es de 320px.
	 */
	public FormField(int style, int[] columnsWidth) {
		super();
		_style = style;
		_columnsWidth = columnsWidth;
		_columns = _columnsWidth.length;
		this.putFirstSeparator();
	}

	/**
	 * Crea un nuevo objeto de tipo FormField listo para agregar campos. Por default se colocara una linea separatoria
	 * entre "fila" y "fila".
	 *
	 * @param style		El estilo de la segunda columna del formulario, puede ser STYLE_READ_ONLY, STYLE_EDITABLE,
	 *                     STYLE_FIELD_CUSTOM. En caso de indicar un valor distinto a uno de estos, se creara el campo como
	 *                     STYLE_READ_ONLY.
	 * @param columnsWidth Un array de ints conteniendo la medida de cada columna. La sumatoria de los elementos debe ser
	 *                     igual al maximo ancho disponible de pantalla. Para el BlackBerry 8310 es de 320px.
	 * @param addSeparator Indica si se debe agregar, o no, una linea separatoria debajo de cada "fila" del formulario.
	 */
	public FormField(int style, int[] columnsWidth, boolean addSeparator) {
		super();
		_style = style;
		_columnsWidth = columnsWidth;
		_columns = _columnsWidth.length;
		_addSeparator = addSeparator;
		this.putFirstSeparator();
	}

	/**
	 * Crea un nuevo objeto de tipo FormField listo para agregar campos. Por default se colocara una linea separatoria
	 * entre "fila" y "fila".
	 *
	 * @param style		El estilo de la segunda columna del formulario, puede ser STYLE_READ_ONLY, STYLE_EDITABLE,
	 *                     STYLE_FIELD_CUSTOM. En caso de indicar un valor distinto a uno de estos, se creara el campo como
	 *                     STYLE_READ_ONLY.
	 * @param columns	  La cantidad de columnas que tendra el formulario. Como no se indica el ancho de las mismas
	 *                     entonces seran del mayor ancho posible y de igual ancho cada.
	 * @param addSeparator La cantidad de columnas que tendra el formulario.
	 */
	public FormField(int style, int columns, boolean addSeparator) {
		super();
		_columns = columns;
		_addSeparator = addSeparator;
		_style = style;
		this.putFirstSeparator();
	}

	/**
	 * Agrega una fila al formulario, con el estilo que ya tiene el formulario entero.
	 *
	 * @param label El label a colocar.
	 * @param value El value a colocar.
	 *
	 * @return true cuando se agrego la fila correctamente. false cuando no.
	 */
	public boolean addField(String label, String value, long focusable) {
		return this.addField(label, value, _style, _maximumChars, focusable);
	}

	/**
	 * Agrega una fila al formulario.
	 *
	 * @param label		El label a colocar.
	 * @param value		El value a colocar.
	 * @param maximumChars La maxima cantidad de caracteres permitidos para el campo. Es decir, se creara el campo como
	 *                     style STYLE_EDITABLE
	 *
	 * @return true cuando se agrego la fila correctamente. false cuando no.
	 */
	public boolean addField(String label, String value, int maximumChars, long focusable) {
		return this.addField(label, value, STYLE_EDITABLE, maximumChars, focusable);
	}

	/**
	 * Agrega todos los elementos del par labels-values al formulario, con el estilo que ya tiene el formulario entero.
	 *
	 * @param labels Un {@link Vector} con los labels a colocar.
	 * @param values Un {@link Vector} con los valores a colocar.
	 *
	 * @return true cuando se pudieron agregar todos los campos. false cuando no se pudo agregar alguno de los campos.
	 */
	public boolean addField(Vector labels, Vector values) {
		return this.addField(labels, values, _style, _maximumChars);
	}

	/**
	 * Agrega todos los elementos del par labels-values al formulario.
	 *
	 * @param labels	   Un {@link Vector} con los labels a colocar.
	 * @param values	   Un {@link Vector} con los valores a colocar.
	 * @param maximumChars La maxima cantidad de caracteres permitidos para los campos editables (es decir, que tenga un
	 *                     style STYLE_EDITABLE) que se van a agregar
	 *
	 * @return true cuando se pudieron agregar todos los campos. false cuando no se pudo agregar alguno de los campos.
	 */
	public boolean addField(Vector labels, Vector values, int maximumChars, long focusable) {
		return this.addField(labels, values, STYLE_EDITABLE, maximumChars, focusable);
	}

	/**
	 * Agrega todos los elementos del par labels-values al formulario.
	 *
	 * @param labels	   Un {@link Vector} con los labels a colocar.
	 * @param values	   Un {@link Vector} con los valores a colocar.
	 * @param style		El estilo de la segunda columna del formulario para este conjunto de campos que se van a
	 *                     agregar, puede ser STYLE_READ_ONLY, STYLE_EDITABLE, STYLE_FIELD_CUSTOM. En caso de indicar un
	 *                     valor distinto a uno de estos, se creara el campo como STYLE_READ_ONLY.
	 * @param maximumChars La maxima cantidad de caracteres permitidos para los campos editables (es decir, que tenga un
	 *                     style STYLE_EDITABLE) que se van a agregar
	 *
	 * @return true cuando se pudieron agregar todos los campos. false cuando no se pudo agregar alguno de los campos.
	 */
	protected boolean addField(Vector labels, Vector values, int style, int maximumChars, long focusable) {
		boolean ret = true;

		Enumeration labelsElements = labels.elements();
		Enumeration valuesElements = values.elements();
		while (labelsElements.hasMoreElements() && valuesElements.hasMoreElements()) {
			String aLabel = (String) labelsElements.nextElement();
			String aValue = (String) valuesElements.nextElement();

			if (aLabel != null && aValue != null)
				ret = this.addField(aLabel, aValue, style, maximumChars, focusable);
			else
				ret = false;
		}

		return ret;
	}

	/**
	 * Agrega una fila al formulario.
	 *
	 * @param label		El label a colocar.
	 * @param value		El value a colocar.
	 * @param style		El estilo de la segunda columna del formulario para este conjunto de campos que se van a
	 *                     agregar, puede ser STYLE_READ_ONLY, STYLE_EDITABLE, STYLE_FIELD_CUSTOM. En caso de indicar un
	 *                     valor distinto a uno de estos, se creara el campo como STYLE_READ_ONLY.
	 * @param maximumChars La maxima cantidad de caracteres permitidos para los campos editables (es decir, que tenga un
	 *                     style STYLE_EDITABLE) que se van a agregar
	 *
	 * @return true cuando se agrego la fila correctamente. false cuando no.
	 */
	public boolean addField(String label, String value, int style, int maximumChars, long focusable) {
		GridFieldManager aGrid;

		if (_columnsWidth != null)
			aGrid = new GridFieldManager(_columnsWidth, 0);
		else
			aGrid = new GridFieldManager(_columns, 0);

		aGrid.add(new LabelField(label));

		Field ef_value = null;
		switch (style) {
			case STYLE_READ_ONLY:
				ef_value = new LabelField(value, focusable);
				break;
			case STYLE_EDITABLE:
				ef_value = new BasicEditField("", value, maximumChars, style);
				break;
			default:
				ef_value = new LabelField(value);
				break;
		}
		aGrid.add(ef_value);

		this.add(aGrid);
		if (_addSeparator)
			this.add(new SeparatorField());

		_fields.put(label, value);
		return true;

	}

	/** @return the _fields */
	public Hashtable get_fields() {
		return _fields;
	}

	/** @return the _addSeparator */
	public boolean is_addSeparator() {
		return _addSeparator;
	}

	/** @param addSeparator the _addSeparator to set */
	public void set_addSeparator(boolean addSeparator) {
		_addSeparator = addSeparator;
	}

	/** @return the _columns */
	public int get_columns() {
		return _columns;
	}

}
